<template>
  <div class="hy-table" :style="{ height: tableHeight > 0 ? `${tableHeight}px` : '' }">
    <ul class="table-header flex py-2" :style="getHeaderStyle">
      <li
        class="flex-1 text-ellipsis"
        v-for="(item, id) in columns"
        :key="id"
        :class="item.class"
        :style="styles[id]"
      >
        <slot :name="`${item.field}Header`" :row="item">
          <div>{{ item.title }}</div>
        </slot>
      </li>
    </ul>
    <div class="table-body" :style="{ transform: `translate3d(0, -${translateY}px, 0)` }">
      <ul
        class="table-body-item flex py-2"
        v-for="(item, index) in animationData"
        :style="[
          getColumnsStyle,
          striped && index % 2 == 0
            ? `background-color:${oddRowBGC}`
            : `background-color:${evenRowBGC}`,
        ]"
        :key="item.index"
      >
        <li
          class="flex-1 text-ellipsis"
          v-for="(col, index) in columns"
          :key="index"
          :class="col.class"
          :style="styles[index]"
        >
          <slot :name="col.field" :row="{ ...item, field: col.field, index: item.index }">
            <span>{{ col.isSerialNumber ? item.index + 1 : item[col.field] }}</span>
          </slot>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { ref, onMounted, computed, onUnmounted } from 'vue';
export default {
	name : 'HyTable',
	// 由于vue无法验证对象内部的属性，所以只能一个个暴露出来
	props : {
		// 请求后台的URL
		url : {
			type : String,
			required : true,
		},
		// 请求方式
		method : {
			type : String,
			default : 'GET',
		},
		contentType : {
			type : String,
			default : 'application/json',
		},
		// 是否显示行间隔色
		striped : {
			type : Boolean,
			default : true,
		},
		// 传递参数
		queryParams : {
			type : Object,
			default : () => ({}),
		},
		// 是否显示分页
		pagination : {
			type : Boolean,
			default : true,
		},
		// 初始化加载第一页，默认第一页
		pageNumber : {
			type : [String, Number],
			default : 1,
		},
		// 每页的记录行数
		pageSize : {
			type : [String, Number],
			default : 10,
		},
		// 可供选择的每页的行数
		pageList : {
			type : Array,
			default : () => [10, 25, 50, 100],
		},
		// 是否启用点击选中行
		clickToSelect : {
			type : Boolean,
			default : true,
		},
		// 定义表格的高度
		height : {
			type : [String, Number],
		},
		// 表头背景色
		headerBGC : {
			type : String,
			default : 'rgba(0, 140,255)',
		},
		// 表头文字大小
		headerFontSize : {
			type : [String, Number],
			default : 32,
		},
		// 列表文字大小
		columnsFontSize : {
			type : [String, Number],
			default : 32,
		},
		// 列表偶数背景色
		oddRowBGC : {
			type : String,
			default : 'rgba(0,0,0,.5)',
		},
		// 列表奇数背景色
		evenRowBGC : {
			type : String,
		},
		// 展示多少个
		rowNum : {
			type : [String, Number],
			default : 10,
		},
		/**
     * title 标题
     * field 字段映射/列表插槽
     * formatter 格式化
     * radio 是否显示单选radio 默认 flase
     * checkbox 是否显示多选checkbox 默认 flase
     * field+Header 表头插槽
     * class 该列的class
     * style 样式
     * width 每列的宽
     * align 设置该列数据如何对齐left, right, center 默认 center
     */
		columns : {
			type : Array,
			required : true,
		},
		data : {
			type : Array,
			default : () => [],
		},
	},
	setup (ctx) {
		let styles = ref([]);
		let tableHeight = ref(0);
		let tableBodyItemHeight = ref(0);
		let translateY = ref(0);
		let animationData = ref([]);
		let tableBodyDom = null;
		let task = null;
		let index = 1;

		ctx.data.forEach((item, index) => {
			animationData.value.push({ ...item, index });
		});

		let toPx = (n) => {
			if (n) {
				if (String(n).endsWith('px')) {
					return n;
				}
				return `${n}px`;
			}
			return '';
		};

		let stopAnimation = () => {
			if (ctx.data.length <= ctx.rowNum) return;
			animationData.value = [...animationData.value, ...animationData.value];
			task = setInterval(() => {
				if (index >= ctx.data.length) {
					// 防止闪动
					setTimeout(function () {
						index = 1;
						tableBodyDom.style.transition = '';
						tableBodyDom.style.transform = 'translate3d(0,0, 0)';
					}, 300);
				}
				tableBodyDom.style.transition = 'all 0.3s linear';
				translateY.value = tableBodyItemHeight.value * index;
				index++;
			}, 1000);
		};

		// 更新样式
		let updateStyle = () => {
			let list = [];
			let align = 'center';
			ctx.columns.forEach((item) => {
				if (item.align) {
					align = item.align;
				}
				let sty = `text-align:${align};`;
				let width = toPx(item.width);
				if (width) {
					sty += `flex: 0 0 ${width} !important;`;
				}
				list.push(sty);
				styles.value = list;
			});
		};

		let getHeaderStyle = computed(() => {
			let sty = '';
			if (ctx.headerBGC) {
				sty += `background-color:${ctx.headerBGC};`;
			}
			let headerFontSize = toPx(ctx.headerFontSize);
			if (headerFontSize) {
				sty += `font-size:${headerFontSize};`;
			}
			return sty;
		});

		let getColumnsStyle = computed(() => {
			let sty = '';
			let columnsFontSize = toPx(ctx.columnsFontSize);
			if (columnsFontSize) {
				sty += `font-size:${columnsFontSize};`;
			}
			return sty;
		});

		onMounted(() => {
			let tableHeader = document.querySelector('.table-header').clientHeight;
			tableBodyItemHeight.value = document.querySelector('.table-body-item').clientHeight;
			tableBodyDom = document.querySelector('.table-body');
			tableHeight.value = tableBodyItemHeight.value * ctx.rowNum + tableHeader;
			updateStyle();
			stopAnimation();
		});

		onUnmounted(() => {
			clearInterval(task);
		});

		return {
			getHeaderStyle,
			getColumnsStyle,
			tableHeight,
			styles,
			animationData,
			translateY,
		};
	},
};
</script>

<style lang="scss" scoped>
.hy-table {
  overflow: hidden;
}
.text-ellipsis {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.striped {
  background: rgba(0, 0, 0, 0.5);
}
.py-2 {
  padding: 18px 10px;
}
.table-header {
  position: relative;
  z-index: 10;
}
</style>
